/*
 * WTP_GPRS.c
 *
 *  Created on: 18-feb-2011
 *      Author: danny
 */

/****************************************************************************
Wireless_UART.c

Application Note: This simple application forms a point to point wireless uart with ACKs.
Power either the 13192SARD or GB60 EVB with a MC13192 2.2 IC and connect the UART1 on the EVB and
Uart1 for 13192SARD.  If you have legacy ARD boards this by default must use UART2.

UNZIP this in the apps directory with other app demos.

Download the same code to 2 boards.

Set the Hyperterms for 38400 No flow control.
Type a character on one of the hyperterms.  It will send the character via MC13192 to
the other board and display it on its respective Hyperterm.  It will be displayed and the rx
board will send back "ACK".  The TX board will be listening for the ACK.  On every timeout
the TX will retransmit the character.  The number of successive tries is reflected 
on the LEDs.  1 light is one retry.  2 is two retries.  3 is three retries etc.

If the ack is received the LEDs are reset.
If the ack is not received by the 5th retry the character is dropped and the
LEDs are reset.

The timeout period is controlled by TIMEOUT_PERIOD
The number of retries is kept in RETRY_COUNT.  Note retries past 5 will reset

Also, on the GB60EVBs COM_SW 4 must be on to allow the RX on the UART2 to work.

$Author: b06900 $
$Date: 2008/03/05 22:49:28 $
$Name:  $
****************************************************************************/
#include "WTP.h"
#ifdef TERMINAL

#include <hidef.h> /* for EnableInterrupts macro */
#include <stdio.h>
#include "pub_def.h"
#include "APP_SMAC_API.h"
#include "freescale_radio_hardware.h"
#include "simple_phy.h"
#include "simple_mac.h"
#include "LCD.h"
#include "SCI.h"
#include "ascii_utilities.h"

//#define DEST_ADDRESS 0

/////////////////////////////
/* note: Buad Rate = 38400 */
/////////////////////////////


/*Global Variables*/
UINT8 gu8RTxMode;
static UINT8 	gu8WTPSourceID[16];
static UINT8 	gu8BreakAddress;

extern UINT8 gu8SCIDataFlag;
extern UINT8 gu8SCIData[128];
extern UINT8 gu8SCIDataCounter;
UINT32 	gu8RFDataCounter = 0;
UINT8 	gu8RecvData[125];
UINT8 	gu8UARTbuffer[10];
INT8 	gi8AppStatus = 0;

UINT8 	gu8WTPSourceIDLength = 0;
UINT8 	gu8LinkQuality[254];
UINT8   gu8PackageLength = 0;
UINT8 	gu8SupDestAddress = 1;
UINT8 	gu8SourceAddress = 0;
UINT8 	gu8AddressCount = 0;
UINT8 	gu8ReplaceAddress = 0;

#define TIMEOUT_PERIOD 0x1000
#define TIMEOUT_RECEIVE 0xA000

#define RETRY_COUNT 4
#define BROADCAST_COUNT 2

UINT8 gu8LinkQualityRx = 0;
UINT8 gu8LinkQualityTx = 0;

void main(void)
{
    static tRxPacket gsRxPacket;
    static tTxPacket gsTxPacket;
    static UINT8 gau8RxDataBuffer[128];
    static UINT8 gau8TxDataBuffer[128];
    UINT8 	u8RetryNo = 0;
    UINT8 	u8Count = 0;
    UINT8 	u8DataCounter;
    UINT8 	i = 0;

  /* Initialize the packet.*/
    gsTxPacket.u8DataLength = 0;
    gsTxPacket.pu8Data = &gau8TxDataBuffer[0];
    gsRxPacket.u8DataLength = 0;
    gsRxPacket.pu8Data = &gau8RxDataBuffer[0];
    gsRxPacket.u8MaxDataLength = 128;
    gsRxPacket.u8Status = 0;

    MCUInit();
    RadioInit();
     
  
    /******************************************************************
     *   To adjust output power call the MLME_MC13192_PA_output_adjust() with:
     * 
     *   MAX_POWER     (+3 to +5dBm)
     *   NOMINAL_POWER (0 dBm)
     *   MIN_POWER     ~(-16dBm)
     *     
     *   or somewhere custom ? (0-15, 11 (NOMINAL_POWER) being Default power)
	 *
     *****************************************************************
     */
     
    (void)MLMEMC13192PAOutputAdjust(OUTPUT_POWER);    	//Set MAX power setting
 /* MLMEMC13192PAOutputAdjust(MIN_POWER);    			//Set MIN power setting */
 /* MLMEMC13192PAOutputAdjust(NOMINAL_POWER);    		//Set Nominal power setting */
     
    /* Init LED's */
    LED1 = 1; /* Default is off */
#ifdef gTargetXBEE_d
    if (SIP) {
      LED2_SIP = 1;
    } else {
      LED2 = 1;
    }
#else
    LED2 = 1;
#endif
    LED3 = 1;
    LED4 = 1;
    
    LED1DIR = 1; /*Output*/
#ifdef gTargetXBEE_d
    if (SIP) {
      LED2DIR_SIP = 1;
    } else {
      LED2DIR = 1;
    }
#else
    LED2DIR = 1;
#endif
    LED3DIR = 1;
    LED4DIR = 1;
    
    PB0PU = 1;     /* Pushbutton directions and pull-ups for bootloader*/
    PB0DIR = 0;
    PB1PU = 1;
    PB1DIR = 0;
    PB2PU = 1;
    PB2DIR = 0;
    PB3PU = 1;
    PB3DIR = 0;;
    
    
    (void)MLMESetMC13192ClockRate(0);  	// Set initial Clk speed 
     
    UseExternalClock();    				// switch clock sources 
     
    SCIInitGeneric(8000000, 38400, DEFAULT_SCI_PORT);      
   
    SCITransmitStr("RESET TERMINAL\r\n");
    EnableInterrupts;
        
    gi8AppStatus = INITIAL_STATE;                 		 // Initial Mode
         
    if (MLMESetChannelRequest(CHANNEL_NUMBER) == SUCCESS) 
    {
   	
		gi8AppStatus = RECEIVER_ALWAYS_ON;
		gu8BreakAddress = 0;
    }
       
//****************************************************************************
//       
//    start of main loop
//        
//****************************************************************************

    for(;;) {

            switch (gi8AppStatus) {

                case IDLE_STATE:
                    /* Switch to RECEIVER_ALWAYS_ON */
                    gi8AppStatus= RECEIVER_ALWAYS_ON;
                    break;
                    
                case RECEIVER_ALWAYS_ON:
                        u8RetryNo = 0;
                        (void)MLMERXEnableRequest(&gsRxPacket, 0);
                        LOW_POWER_WHILE();
                    break;
                    
                case WAITING_FOR_ACK:
                    /* Do nothing.  Go to sleep waiting for TO or RX_IRQ */
                    break;
            
                case TRANSMIT_DATA:
                    gi8AppStatus= IDLE_STATE;

                    if (MLMERXDisableRequest() != SUCCESS) { /* Turn off the RX forever mode. */
                        gi8AppStatus= TRANSMIT_DATA;
                        break;
                    }
                    gau8TxDataBuffer[1] = (0x1F <<3|u8RetryNo);  		//Transmision retry number                    
					gau8TxDataBuffer[0] = TERMINAL_ADDRESS;
					
					for(u8DataCounter = 2; u8DataCounter < 11; u8DataCounter++) gau8TxDataBuffer[u8DataCounter]=gu8SCIData[0];
					gau8TxDataBuffer[11] = '\0';    /* Sending String */
					gsTxPacket.u8DataLength = 12;
						
                    if ((MCPSDataRequest(&gsTxPacket) == SUCCESS))  /* transmit data */
                    {
                        gi8AppStatus = WAITING_FOR_ACK; 
                        (void)MLMERXEnableRequest(&gsRxPacket, TIMEOUT_PERIOD);
                    }
                    gu8SCIDataFlag = 0;
                    break;
                                        
                case TRANSMIT_ACK:
                    gi8AppStatus= RECEIVER_ALWAYS_ON;
                    gau8TxDataBuffer[0] = TERMINAL_ADDRESS;
                    (void)memmove (gau8TxDataBuffer+1,ACK,3);
                    gsTxPacket.u8DataLength = 4;
                    if(gu8BreakAddress !=0 && gu8AddressCount >= gu8BreakAddress && gu8SourceAddress == gu8AddressCount)
                    {
                    	gau8TxDataBuffer[4] = gu8SourceAddress + 1;
                    	gu8AddressCount--;
						gsTxPacket.u8DataLength = 5;
						SCIStartTransmit('>');
                    }
                    if((gu8BreakAddress !=0) &&((gu8AddressCount - (gu8BreakAddress-1)) == 0)&&(gu8SourceAddress == gu8ReplaceAddress))
                    {
                    	gau8TxDataBuffer[4] = gu8BreakAddress;
						gsTxPacket.u8DataLength = 5;
						gu8SupDestAddress--;
						gu8BreakAddress = 0;
						SCIStartTransmit('-');
                    }
                    if(gu8SourceAddress == BRODCAST_ADDRESS)
                    {
                    	if(gu8RFDataCounter == BROADCAST_COUNT && gu8SupDestAddress < 255)
						{
							gu8LinkQuality[gu8SupDestAddress]= gu8LinkQualityTx;
							gau8TxDataBuffer[4] = gu8SupDestAddress;
							gu8SupDestAddress++;
						}else gau8TxDataBuffer[4] = BRODCAST_ADDRESS;
                    	
                    	(void)memmove (gau8TxDataBuffer+5,gu8WTPSourceID,gu8WTPSourceIDLength);
                    	 gsTxPacket.u8DataLength = gu8WTPSourceIDLength + 5;
					}
                    
                    if(MCPSDataRequest(&gsTxPacket) == SUCCESS)/* transmit data */
                    {
						if(gsTxPacket.u8DataLength==5)
						{
							gi8AppStatus = WAITING_FOR_ACK; 
							(void)MLMERXEnableRequest(&gsRxPacket, TIMEOUT_PERIOD);
						}
						if(gu8RFDataCounter == BROADCAST_COUNT)
						{
							gu8BreakAddress = 0;
							u8Count = 1;
							while((gu8LinkQuality[gu8SupDestAddress-1] > gu8LinkQuality[u8Count])&&(u8Count < gu8SupDestAddress-1))
							{
								u8Count++;
							}
							if(u8Count != gu8SupDestAddress-1)
							{
								gu8BreakAddress = u8Count;
								gu8AddressCount = gu8SupDestAddress - 1;
								gu8ReplaceAddress = gu8SupDestAddress;
								gu8SupDestAddress++;
								SCIStartTransmit('*');
							}
							gu8WTPSourceIDLength = 0;
							gu8RFDataCounter = 0;
						}
                    }
                    break;
                    
                case TIMEOUT_STATE:
                    if (u8RetryNo < RETRY_COUNT) 
                    {
                        gi8AppStatus= TRANSMIT_DATA;    /* Retransmit. */
                        u8RetryNo++;
                    } else 
                    {
                        /* Give up on packet. */
                        gi8AppStatus= RECEIVER_ALWAYS_ON;
                        u8RetryNo = 0;
                    }
                    break;
            } 
            if (gu8SCIDataFlag == 1)
            {
                gi8AppStatus= TRANSMIT_DATA;
            }
        }
    }

void MCPSDataIndication(tRxPacket *gsRxPacket) 
    {
    UINT8 	i = 0;
        /*
         * Place your code here to handle a mac layer data indication.
         * RX packet is in the global structure
         * gsRxPacket.dataLength and gsRxPacket.data
    	 */
        if (gsRxPacket->u8Status == SUCCESS) 
        {
            /* Packet received */
        	if (memcmp(&gsRxPacket->pu8Data[1], ACK, 3) == 0) // Test if ACK
            {
            	if(((gsRxPacket->pu8Data[0] > 0)&&(gsRxPacket->pu8Data[0] < gu8SupDestAddress))||(gsRxPacket->pu8Data[0] == BRODCAST_ADDRESS))
				{
					if (gi8AppStatus== WAITING_FOR_ACK )
					{
						gu8LinkQualityRx = MLMELinkQuality();
						gi8AppStatus= RECEIVER_ALWAYS_ON; /* go back to rx_mode. */
					}
					
				}
            	return;
            }    /* Not an ACK */ 
            if((gsRxPacket->pu8Data[0] > 0)&&(gsRxPacket->pu8Data[0] < gu8SupDestAddress))
			{
				gu8SourceAddress = gsRxPacket->pu8Data[0];
				SCITransmitStr("\n\rDES");
				UTILInt2String((gsRxPacket->pu8Data[0]),gu8UARTbuffer);
				trimWhiteSpace(gu8UARTbuffer);
				SCITransmitStr(gu8UARTbuffer);
				gi8AppStatus = TRANSMIT_ACK;
				return;
			}
            if(gsRxPacket->pu8Data[0] == BRODCAST_ADDRESS)
			{   				
				gu8SourceAddress = gsRxPacket->pu8Data[0];
				gu8LinkQualityRx = MLMELinkQuality();
				SCITransmitStr("\n\rBROD");
				if(gu8BreakAddress == 0)
				{
					if(gu8WTPSourceIDLength == 0)
					{
						gu8WTPSourceIDLength = gsRxPacket->u8DataLength - 3;					
						(void)memmove (gu8WTPSourceID,&gsRxPacket->pu8Data[3],gu8WTPSourceIDLength);
						SCITransmitStr("@");
						SCITransmitStr(gu8WTPSourceID);
					}
					if(memcmp(&gsRxPacket->pu8Data[3], gu8WTPSourceID, gu8WTPSourceIDLength) == 0)
					{
						if(gsRxPacket->pu8Data[2] != 0 &&gsRxPacket->pu8Data[2] != 0xff)
						{
							gu8LinkQualityTx = (UINT8)(gsRxPacket->pu8Data[2] + gu8LinkQualityRx)/2;
							UTILInt2String((gu8LinkQualityTx),gu8UARTbuffer);
							trimWhiteSpace(gu8UARTbuffer);
							SCITransmitStr("$");
							SCITransmitStr(gu8UARTbuffer);
						}
					if(gu8RFDataCounter  < BROADCAST_COUNT) gu8RFDataCounter++;	
					gi8AppStatus = TRANSMIT_ACK;
					}
				} 
			}else   /* Not my Dest */
			{
				SCITransmitStr("\n\r");
				SCITransmitStr("\n\rNO");	
				UTILInt2String((gsRxPacket->pu8Data[0]),gu8UARTbuffer);
				trimWhiteSpace(gu8UARTbuffer);
				SCITransmitStr(gu8UARTbuffer);
			}
        }
        if (gsRxPacket->u8Status == TIMEOUT) 
        {
            /* Received TIMEOUT */
            gi8AppStatus = TIMEOUT_STATE;        
        }        
    }

    void MLMEMC13192ResetIndication(void) 
    {
        //Notifies you that the MC13192 has been reset.
        //Application must handle this here.

    }
#endif
